<template>
	<div class="course-manager">
		<div class="course-manager__body">
			<aside class="course-manager__sidebar">
				<div class="sidebar__cta">
					<el-button type="primary" size="large" class="sidebar__post-btn" @click="openSubmissionDrawer">
						投稿
					</el-button>
				</div>
				<el-menu
					class="sidebar__menu"
					:default-active="activeSection"
					background-color="#ffffff"
					active-text-color="#409eff"
					@select="handleSectionSelect"
				>
					<el-menu-item index="content">
						<span>内容管理</span>
					</el-menu-item>
					<el-menu-item index="data">
						<span>数据中心</span>
					</el-menu-item>
					<el-menu-item index="interaction">
						<span>互动管理</span>
					</el-menu-item>
				</el-menu>
			</aside>

			<main class="course-manager__main">
				<section v-if="activeSection === 'content'" class="section">
					<header class="section__header">
						<div>
							<h1>内容管理</h1>
							<p>维护课程信息、定价与章节，确保学习路径清晰完整。</p>
						</div>
						<el-button type="primary" size="large" @click="handleAddCourse">新增课程</el-button>
					</header>

					<el-card shadow="never" class="section__card">
						<template #header>
							<div class="card-header">
								<span>我的课程（{{ courses.length }}）</span>
							</div>
						</template>

						<el-empty v-if="!courses.length" description="暂无课程，立即创建您的第一套课程吧" />
						  <el-table v-else :data="courses" stripe style="width: 100%" :row-key="getCourseRowKey">
							<el-table-column prop="title" label="课程标题" min-width="220" show-overflow-tooltip />
							<el-table-column prop="category" label="分类" min-width="120">
								<template #default="{ row }">
									<el-tag type="info">{{ resolveCategoryName(row.category) }}</el-tag>
								</template>
							</el-table-column>
							<el-table-column prop="price" label="价格" min-width="120">
								<template #default="{ row }">¥{{ row.price.toFixed(2) }}</template>
							</el-table-column>
							<el-table-column label="章节 / 课时" min-width="160">
								<template #default="{ row }">
									{{ row.chapters.length }} / {{ countLessons(row) }}
								</template>
							</el-table-column>
							<el-table-column label="报名人数" min-width="140">
								<template #default="{ row }">{{ row.enrollments.toLocaleString() }}</template>
							</el-table-column>
							<el-table-column label="评分" min-width="100">
								<template #default="{ row }">
									<strong>{{ row.rating.toFixed(1) }}</strong>
								</template>
							</el-table-column>
							<el-table-column label="状态" min-width="120">
								<template #default="{ row }">
									  <el-tag :type="resolveStatusMeta(row.status).type">{{ resolveStatusMeta(row.status).label }}</el-tag>
								</template>
							</el-table-column>
							<el-table-column prop="createdAt" label="创建时间" min-width="160" />
							<el-table-column label="操作" fixed="right" min-width="200">
								<template #default="{ row }">
									<el-button type="primary" link @click="handleEditCourse(row)">编辑</el-button>
									<el-button type="danger" link @click="handleDeleteCourse(row.id)">删除</el-button>
								</template>
							</el-table-column>
						</el-table>
					</el-card>
				</section>

				<section v-else-if="activeSection === 'data'" class="section">
					<header class="section__header">
						<div>
							<h1>数据中心</h1>
							<p>追踪课程表现、收入与学员行为，及时调整教学策略。</p>
						</div>
					</header>

					<div class="metrics-grid">
						<el-card v-for="card in metricCards" :key="card.title" shadow="never" class="metric-card">
							<span class="metric-card__title">{{ card.title }}</span>
							<span class="metric-card__value">{{ card.value }}</span>
							<span class="metric-card__note">{{ card.note }}</span>
						</el-card>
					</div>

					<div class="data-layout">
						<el-card shadow="never" class="data-card">
							<template #header>
								<div class="card-header">
									<span>课程表现排行</span>
									<small>按报名人数排序</small>
								</div>
							</template>
							  <el-table :data="topCourses" size="small" :row-key="getCourseRowKey">
								<el-table-column type="index" width="60" label="#" />
								<el-table-column prop="title" label="课程" min-width="200" show-overflow-tooltip />
								<el-table-column prop="enrollments" label="报名" min-width="120">
									<template #default="{ row }">{{ row.enrollments.toLocaleString() }}</template>
								</el-table-column>
								<el-table-column prop="comments" label="评论" min-width="100" />
								<el-table-column prop="rating" label="评分" min-width="100">
									<template #default="{ row }">
										<strong>{{ row.rating.toFixed(1) }}</strong>
									</template>
								</el-table-column>
								<el-table-column label="收入预估" min-width="140">
									<template #default="{ row }">¥{{ (row.price * row.enrollments).toLocaleString() }}</template>
								</el-table-column>
							</el-table>
						</el-card>

						<el-card shadow="never" class="data-card">
							<template #header>
								<div class="card-header">
									<span>发布进度</span>
									<small>掌握当前各状态课程占比</small>
								</div>
							</template>
							<div class="progress-list">
								<div class="progress-item">
									<div class="progress-item__label">发布率</div>
									<el-progress :percentage="publishRate" :stroke-width="12" />
								</div>
								<div class="progress-item">
									<div class="progress-item__label">审核中（{{ reviewCount }}）</div>
									<el-progress :percentage="reviewRate" status="warning" :stroke-width="12" />
								</div>
							</div>

							<el-descriptions :column="1" border class="data-summary">
								<el-descriptions-item label="平均完课率">{{ averageCompletionRate }}%</el-descriptions-item>
								<el-descriptions-item label="高活跃课程">{{ highEngagementCourse }}</el-descriptions-item>
								<el-descriptions-item label="近7天新增评论">{{ weeklyComments }}</el-descriptions-item>
							</el-descriptions>
						</el-card>
					</div>
				</section>

				<section v-else class="section">
					<header class="section__header">
						<div>
							<h1>互动管理</h1>
							<p>及时回复学员提问与反馈，维护良好学习氛围。</p>
						</div>
					</header>

					<el-card shadow="never" class="section__card">
						<template #header>
							<div class="card-header">
								<span>评论列表（{{ comments.length }}）</span>
							</div>
						</template>

						<el-empty v-if="!comments.length" description="暂未收到评论" />
						<el-table v-else :data="comments" stripe :row-key="getCommentRowKey">
							<el-table-column type="expand">
								<template #default="{ row }">
									<div class="reply-list">
										<div v-if="!row.replies.length" class="reply-list__empty">暂无回复</div>
										<div v-for="reply in row.replies" :key="reply.id" class="reply-item">
											<div class="reply-item__meta">
												<strong>{{ reply.author }}</strong>
												<span>{{ formatDate(reply.createdAt) }}</span>
											</div>
											<p>{{ reply.content }}</p>
										</div>
									</div>
								</template>
							</el-table-column>
							<el-table-column prop="courseTitle" label="课程" min-width="200" show-overflow-tooltip />
							<el-table-column prop="userName" label="学员" min-width="120" />
							<el-table-column prop="rating" label="评分" min-width="100">
								<template #default="{ row }">
									<el-tag type="warning">{{ row.rating }} ★</el-tag>
								</template>
							</el-table-column>
							<el-table-column prop="content" label="评论内容" min-width="260" show-overflow-tooltip />
							<el-table-column prop="createdAt" label="时间" min-width="160">
								<template #default="{ row }">{{ formatDate(row.createdAt) }}</template>
							</el-table-column>
							<el-table-column label="操作" fixed="right" min-width="180">
								<template #default="{ row }">
									<el-button type="primary" link @click="openReplyDialog(row)">回复</el-button>
									<el-button type="danger" link @click="handleDeleteComment(row.id)">删除</el-button>
								</template>
							</el-table-column>
						</el-table>
					</el-card>
				</section>
			</main>
		</div>

		<el-drawer
			v-model="submissionDrawerVisible"
			size="60%"
			:with-header="false"
			destroy-on-close
			@closed="resetSubmissionFlow"
		>
			<div class="submission-drawer">
				<header class="submission-drawer__header">
					<h2>投稿课程内容</h2>
					<p>上传章节视频、完善信息，提交后将进入审核流程。</p>
				</header>

				<div v-if="uploadStep === 'upload'" class="submission-upload">
					<el-upload
						drag
						:show-file-list="false"
						accept="video/*"
						:http-request="handleVideoUpload"
						:disabled="uploadingVideo"
					>
						<el-icon class="submission-upload__icon">
							<VideoPlay />
						</el-icon>
						<p class="submission-upload__title">将视频拖曳至此，或点击上传章节视频</p>
						<p class="submission-upload__tips">支持常见视频格式，建议大小不超过 2GB</p>
					</el-upload>
					<div v-if="uploadingVideo" class="submission-upload__progress">
						<el-progress :percentage="videoUploadProgress" :stroke-width="10" striped striped-flow />
					</div>
					<p v-if="uploadError" class="submission-upload__error">{{ uploadError }}</p>
				</div>

				<div v-else class="submission-form">
					<el-card shadow="never" class="submission-form__info">
						<template #header>
							<div class="card-header">
								<span>视频信息</span>
								<el-button type="primary" link @click="backToUpload">重新上传</el-button>
							</div>
						</template>
						<el-descriptions :column="1" border>
							<el-descriptions-item label="文件名">{{ videoDetails.name }}</el-descriptions-item>
							<el-descriptions-item label="文件大小">{{ formatFileSize(videoDetails.size) }}</el-descriptions-item>
							<el-descriptions-item label="视频时长">{{ formattedDuration }}</el-descriptions-item>
						</el-descriptions>
					</el-card>

					<el-form ref="submissionFormRef" :model="submissionForm" :rules="submissionRules" label-width="96px" class="submission-form__fields">
						<el-form-item label="封面">
							<div class="cover-field">
								<div class="cover-preview" v-if="coverImage">
									<img :src="coverImage" alt="视频封面" />
								</div>
								<div v-else class="cover-preview cover-preview--placeholder">自动生成封面载入中...</div>
								<el-upload
									:show-file-list="false"
									accept="image/*"
									:http-request="handleCoverUpload"
								>
									<el-button type="primary" plain>更换封面</el-button>
								</el-upload>
							</div>
						</el-form-item>
						<el-form-item label="标题" prop="title">
							<el-input v-model="submissionForm.title" maxlength="60" show-word-limit placeholder="请输入视频标题" />
						</el-form-item>
						<el-form-item label="分类">
							<el-select v-model="submissionForm.category" clearable placeholder="可选，选择视频分类">
								<el-option v-for="item in categoryOptions" :key="item.value" :label="item.label" :value="item.value" />
							</el-select>
						</el-form-item>
						<el-form-item label="所属课程" prop="courseId">
							<el-select v-model="submissionForm.courseId" placeholder="请选择绑定课程">
								<el-option v-for="course in courseSelectOptions" :key="course.value" :label="course.label" :value="course.value" />
							</el-select>
						</el-form-item>
					</el-form>

					<div class="submission-form__actions">
						<el-button @click="handleSaveDraft">存草稿</el-button>
						<el-button type="primary" @click="handleSubmitSubmission">立即投稿</el-button>
					</div>
				</div>
			</div>
		</el-drawer>

		<el-dialog v-model="courseEditorVisible" width="900px" destroy-on-close @closed="resetCourseForm">
			<template #header>
				<div class="dialog-header">
					<h3>{{ editingCourseId ? '编辑课程' : '新增课程' }}</h3>
					<p>完善课程基础信息与章节结构。</p>
				</div>
			</template>

			<el-form ref="courseFormRef" :model="courseForm" :rules="courseFormRules" label-width="100px" class="course-form">
				<el-form-item label="课程标题" prop="title">
					<el-input v-model="courseForm.title" maxlength="80" show-word-limit placeholder="请输入课程标题" />
				</el-form-item>
				<el-form-item label="课程分类" prop="category">
					<el-select v-model="courseForm.category" placeholder="请选择课程分类">
						<el-option v-for="item in categoryOptions" :key="item.value" :label="item.label" :value="item.value" />
					</el-select>
				</el-form-item>
				<el-form-item label="课程价格" prop="price">
					<el-input-number v-model="courseForm.price" :min="0" :step="1" :precision="2" />
					<span class="course-form__tip">建议根据课时长短与深度制定价格</span>
				</el-form-item>
				<!-- <el-form-item label="课程状态">
					<el-tag :type="resolveStatusMeta(courseForm.status).type">
						{{ resolveStatusMeta(courseForm.status).label }}
					</el-tag>
					<span class="course-form__tip course-form__tip--inline">课程审核存在延迟，若有疑问请联系管理员</span>
				</el-form-item> -->
				<el-form-item label="章节结构">
					<div class="chapters-editor">
						<el-empty v-if="!courseForm.chapters.length" description="尚未添加章节" />
						<div v-for="(chapter, chapterIndex) in courseForm.chapters" :key="chapter.id" class="chapter-card">
							<div class="chapter-card__header">
								<el-input v-model="chapter.title" placeholder="章节标题" />
								<el-button type="danger" text @click="removeChapter(chapterIndex)">删除章节</el-button>
							</div>
							<div class="chapter-card__lessons">
								<div v-for="(lesson, lessonIndex) in chapter.lessons" :key="lesson.id" class="lesson-item">
									<div class="lesson-item__title">
										<el-input v-model="lesson.title" placeholder="课时标题" />
									</div>
									<div class="lesson-item__source">
										<el-select
											v-model="lesson.assetId"
											placeholder="选择已上传的视频"
											@change="handleLessonAssetChange(chapterIndex, lessonIndex)"
										>
											<el-option
												v-for="asset in lessonLibrary"
												:key="asset.id"
												:value="asset.id"
												:label="`${asset.title} · ${formatDuration(asset.duration)}`"
											/>
										</el-select>
										<el-button
											v-if="lesson.assetId && findLessonAsset(lesson.assetId)?.resumeId"
											type="success"
											link
											:loading="downloadingAssetId === lesson.assetId"
											@click="handleDownloadAsset(lesson.assetId)"
										>
											下载视频
										</el-button>
									</div>
									<div class="lesson-item__duration-display">
										<el-tag v-if="lesson.duration" type="info">时长：{{ formatDuration(lesson.duration) }}</el-tag>
										<span v-else class="lesson-item__duration-placeholder">请选择或上传视频以获取时长</span>
									</div>
									<div class="lesson-item__actions">
										<el-upload
											class="lesson-item__upload"
											:show-file-list="false"
											accept="video/*"
											:http-request="getInlineUploadHandler(chapterIndex, lessonIndex)"
										>
											<el-button type="primary" link>上传新视频</el-button>
										</el-upload>
										<div v-if="getInlineUploadProgress(chapterIndex, lessonIndex)" class="lesson-item__progress">
											<el-progress :percentage="getInlineUploadProgress(chapterIndex, lessonIndex)" type="circle" :width="42" />
										</div>
										<el-button type="danger" text @click="removeLesson(chapterIndex, lessonIndex)">删除</el-button>
									</div>
								</div>
								<el-button type="primary" link @click="addLesson(chapterIndex)">+ 添加课时</el-button>
							</div>
						</div>
						<el-button type="primary" plain @click="addChapter">新增章节</el-button>
					</div>
				</el-form-item>
			</el-form>

			<template #footer>
				<div class="dialog-footer">
					<el-button @click="courseEditorVisible = false">取消</el-button>
					<el-button type="primary" @click="handleCourseSubmit">保存</el-button>
				</div>
			</template>
		</el-dialog>

		<el-dialog v-model="replyDialogVisible" width="520px" destroy-on-close @closed="resetReplyForm">
			<template #header>
				<div class="dialog-header">
					<h3>回复评论</h3>
					<p>{{ replyDialogTitle }}</p>
				</div>
			</template>

			<el-form label-width="80px">
				<el-form-item label="回复内容">
					<el-input v-model="replyForm.content" type="textarea" :rows="6" maxlength="400" show-word-limit placeholder="请输入回复内容" />
				</el-form-item>
			</el-form>

			<template #footer>
				<div class="dialog-footer">
					<el-button @click="replyDialogVisible = false">取消</el-button>
					<el-button type="primary" @click="handleSubmitReply">发送回复</el-button>
				</div>
			</template>
		</el-dialog>
	</div>
</template>

<script setup lang="ts">
import { computed, defineAsyncComponent, reactive, ref, watch } from 'vue'
import type { FormInstance, FormRules, UploadRequestOptions } from 'element-plus'
import { ElMessage, ElMessageBox } from 'element-plus'
import { VideoPlay } from '@element-plus/icons-vue'
import type { ApiResponse } from '../../api/types'
import { uploadFileInChunksDirect } from '../../utils/file/upload'
import { downloadFileBlobApi } from '../../api/file/fileDownload'
import { saveBlob } from '../../utils/file/download'
const Navigation = defineAsyncComponent(() => import('../../components/Navigation.vue'))

type SectionKey = 'content' | 'data' | 'interaction'

interface CourseLesson {
	id: string
	title: string
	duration: number
	assetId?: string
}

interface CourseChapter {
	id: string
	title: string
	lessons: CourseLesson[]
}

type CourseStatus = 'REVIEWING' | 'PUBLISHED' | 'REJECTED'

interface LessonAsset {
	id: string
	title: string
	duration: number
	uploadedAt: string
	resumeId?: string
	filePath?: string
	fileName?: string
}

interface CourseListItem {
	id: string
	title: string
	price: number
	category: string
	status: CourseStatus
	createdAt: string
	chapters: CourseChapter[]
	enrollments: number
	rating: number
	comments: number
	completion: number
}

interface CommentReply {
	id: string
	author: string
	content: string
	createdAt: string
}

interface CommentItem {
	id: string
	courseId: string
	courseTitle: string
	userName: string
	rating: number
	content: string
	createdAt: string
	replies: CommentReply[]
}

const activeSection = ref<SectionKey>('content')

const categoryOptions = [
	{ label: '心理成长', value: 'growth' },
	{ label: '认知行为疗法', value: 'therapy' },
	{ label: '家庭关系', value: 'family' },
	{ label: '正念冥想', value: 'mindfulness' },
	{ label: '职业发展', value: 'career' },
]

const createId = () => Math.random().toString(36).slice(2, 10)

const lessonLibrary = reactive<LessonAsset[]>([
	{ id: createId(), title: 'CBT 框架概览', duration: 12 * 60 + 36, uploadedAt: '2025-06-01T09:00:00Z' },
	{ id: createId(), title: '常见认知扭曲', duration: 10 * 60 + 5, uploadedAt: '2025-06-01T10:20:00Z' },
	{ id: createId(), title: '情绪记录表实操', duration: 15 * 60 + 22, uploadedAt: '2025-06-02T08:10:00Z' },
	{ id: createId(), title: '暴露疗法设计', duration: 18 * 60 + 40, uploadedAt: '2025-06-02T09:45:00Z' },
	{ id: createId(), title: '正念的科学依据', duration: 8 * 60 + 45, uploadedAt: '2025-08-01T08:00:00Z' },
	{ id: createId(), title: '呼吸练习', duration: 11 * 60 + 14, uploadedAt: '2025-08-01T09:30:00Z' },
	{ id: createId(), title: '高效打卡策略', duration: 9 * 60 + 30, uploadedAt: '2025-08-03T11:00:00Z' },
	{ id: createId(), title: '倾听与共情', duration: 14 * 60 + 2, uploadedAt: '2025-09-10T10:00:00Z' },
])

const uploadModule = 'resume'
const findLessonAsset = (assetId?: string) => lessonLibrary.find(asset => asset.id === assetId)
const downloadingAssetId = ref<string | null>(null)
const inlineUploadProgress = reactive<Record<string, number>>({})
const getLessonUploadKey = (chapterIndex: number, lessonIndex: number) => `${chapterIndex}-${lessonIndex}`
const getInlineUploadProgress = (chapterIndex: number, lessonIndex: number) =>
	inlineUploadProgress[getLessonUploadKey(chapterIndex, lessonIndex)] ?? 0

const handleDownloadAsset = async (assetId?: string) => {
	if (!assetId) {
		ElMessage.warning('请先选择可下载的视频')
		return
	}
	const asset = findLessonAsset(assetId)
	if (!asset || !asset.resumeId) {
		ElMessage.warning('该视频暂未完成上传，无法下载')
		return
	}
	downloadingAssetId.value = assetId
	try {
		const blob = await downloadFileBlobApi(String(asset.resumeId))
		const fileName = asset.fileName || `${asset.title}.mp4`
		saveBlob(blob, fileName)
		ElMessage.success('视频下载已开始')
	} catch (error) {
		ElMessage.error(error instanceof Error ? error.message : '下载失败，请稍后重试')
	} finally {
		downloadingAssetId.value = null
	}
}

const findAssetIdByTitle = (title: string) => lessonLibrary.find(asset => asset.title === title)?.id ?? ''

const courses = reactive<CourseListItem[]>([
	{
		id: createId(),
		title: '认知行为疗法实战入门',
		price: 299,
		category: 'therapy',
		status: 'PUBLISHED',
		createdAt: '2025-06-18',
		chapters: [
			{
				id: createId(),
				title: '核心理论与模型',
				lessons: [
					{
						id: createId(),
						title: 'CBT 框架概览',
						duration: 12 * 60 + 36,
						assetId: findAssetIdByTitle('CBT 框架概览'),
					},
					{
						id: createId(),
						title: '常见认知扭曲',
						duration: 10 * 60 + 5,
						assetId: findAssetIdByTitle('常见认知扭曲'),
					},
				],
			},
			{
				id: createId(),
				title: '案例拆解',
				lessons: [
					{
						id: createId(),
						title: '情绪记录表实操',
						duration: 15 * 60 + 22,
						assetId: findAssetIdByTitle('情绪记录表实操'),
					},
					{
						id: createId(),
						title: '暴露疗法设计',
						duration: 18 * 60 + 40,
						assetId: findAssetIdByTitle('暴露疗法设计'),
					},
				],
			},
		],
		enrollments: 428,
		rating: 4.8,
		comments: 68,
		completion: 86,
	},
	{
		id: createId(),
		title: '正念冥想 21 天打卡营',
		price: 199,
		category: 'mindfulness',
		status: 'REVIEWING',
		createdAt: '2025-08-02',
		chapters: [
			{
				id: createId(),
				title: '入门基础',
				lessons: [
					{
						id: createId(),
						title: '正念的科学依据',
						duration: 8 * 60 + 45,
						assetId: findAssetIdByTitle('正念的科学依据'),
					},
					{
						id: createId(),
						title: '呼吸练习',
						duration: 11 * 60 + 14,
						assetId: findAssetIdByTitle('呼吸练习'),
					},
				],
			},
			{
				id: createId(),
				title: '习惯养成',
				lessons: [
					{
						id: createId(),
						title: '高效打卡策略',
						duration: 9 * 60 + 30,
						assetId: findAssetIdByTitle('高效打卡策略'),
					},
				],
			},
		],
		enrollments: 312,
		rating: 4.6,
		comments: 41,
		completion: 74,
	},
	{
		id: createId(),
		title: '青少年家庭沟通技巧',
		price: 259,
		category: 'family',
		status: 'REVIEWING',
		createdAt: '2025-09-12',
		chapters: [
			{
				id: createId(),
				title: '亲子对话基础',
				lessons: [
					{
						id: createId(),
						title: '倾听与共情',
						duration: 14 * 60 + 2,
						assetId: findAssetIdByTitle('倾听与共情'),
					},
				],
			},
		],
		enrollments: 0,
		rating: 0,
		comments: 0,
		completion: 0,
	},
])

const statusMeta: Record<CourseStatus, { label: string; type: 'info' | 'warning' | 'success' | 'danger' }> = {
	REVIEWING: { label: '审核中', type: 'warning' },
	PUBLISHED: { label: '已发布', type: 'success' },
	REJECTED: { label: '已驳回', type: 'danger' },
}

const comments = reactive<CommentItem[]>([
	{
		id: createId(),
		courseId: courses[0].id,
		courseTitle: courses[0].title,
		userName: 'Lucy',
		rating: 5,
		content: '老师讲解非常细致，课后练习帮助很大，希望增加更多案例。',
		createdAt: '2025-10-29T10:30:00Z',
		replies: [
			{
				id: createId(),
				author: '讲师团队',
				content: '感谢反馈，11 月我们会新增一组焦虑案例拆解，敬请关注。',
				createdAt: '2025-10-30T08:12:00Z',
			},
		],
	},
	{
		id: createId(),
		courseId: courses[1].id,
		courseTitle: courses[1].title,
		userName: 'Kevin',
		rating: 4,
		content: '打卡安排很清晰，如果能提供更多晨间练习就更好了。',
		createdAt: '2025-11-02T06:20:00Z',
		replies: [],
	},
])

const submissionDrawerVisible = ref(false)
const uploadStep = ref<'upload' | 'details'>('upload')
const uploadingVideo = ref(false)
const videoUploadProgress = ref(0)
const uploadError = ref('')

const videoDetails = reactive({
	file: null as File | null,
	name: '',
	size: 0,
	duration: 0,
	resumeId: '',
	filePath: '',
	fileName: '',
})

const resetVideoMeta = () => {
	videoDetails.file = null
	videoDetails.name = ''
	videoDetails.size = 0
	videoDetails.duration = 0
	videoDetails.resumeId = ''
	videoDetails.filePath = ''
	videoDetails.fileName = ''
	videoUploadProgress.value = 0
}

const coverImage = ref('')

const submissionForm = reactive({
	title: '',
	category: '',
	courseId: '',
})

const submissionFormRef = ref<FormInstance>()

const submissionRules: FormRules = {
	title: [
		{ required: true, message: '请输入视频标题', trigger: 'blur' },
		{ min: 4, max: 60, message: '标题长度需在 4-60 个字符之间', trigger: 'blur' },
	],
	courseId: [{ required: true, message: '请选择所属课程', trigger: 'change' }],
}

const courseSelectOptions = computed(() => courses.map(course => ({
	label: course.title,
	value: course.id,
})))

const resolveStatusMeta = (status: CourseStatus) => statusMeta[status]
const getCourseRowKey = (course: CourseListItem) => course.id
const getCommentRowKey = (comment: CommentItem) => comment.id

const formattedDuration = computed(() => (videoDetails.duration ? formatDuration(videoDetails.duration) : ''))

const ensureDefaultCourseSelection = () => {
	if (!submissionForm.courseId && courseSelectOptions.value.length) {
		submissionForm.courseId = courseSelectOptions.value[0].value
	}
}

const resetSubmissionFlow = () => {
	uploadStep.value = 'upload'
	uploadingVideo.value = false
	uploadError.value = ''
	resetVideoMeta()
	coverImage.value = ''
	submissionFormRef.value?.resetFields()
	submissionForm.title = ''
	submissionForm.category = ''
	submissionForm.courseId = ''
}

const openSubmissionDrawer = (courseId?: string) => {
	submissionDrawerVisible.value = true
	ensureDefaultCourseSelection()
	if (courseId) {
		submissionForm.courseId = courseId
	}
}

const backToUpload = () => {
	uploadStep.value = 'upload'
	submissionFormRef.value?.resetFields()
	submissionForm.title = ''
	coverImage.value = ''
	uploadError.value = ''
	uploadingVideo.value = false
	resetVideoMeta()
}

const handleSectionSelect = (index: string) => {
	activeSection.value = index as SectionKey
}

const extractVideoDetails = (file: File) => new Promise<{ duration: number; cover: string }>((resolve, reject) => {
	const video = document.createElement('video')
	const url = URL.createObjectURL(file)
	video.preload = 'metadata'
	video.src = url
	video.muted = true
	video.playsInline = true
	const cleanup = () => {
		URL.revokeObjectURL(url)
	}
	video.onloadedmetadata = () => {
		const duration = video.duration
		const captureTime = Math.min(duration / 2, 3)
		video.currentTime = Number.isFinite(captureTime) ? captureTime : 0
	}
	video.onerror = () => {
		cleanup()
		reject(new Error('failed to load video'))
	}
	video.onseeked = () => {
		const canvas = document.createElement('canvas')
		canvas.width = video.videoWidth
		canvas.height = video.videoHeight
		const ctx = canvas.getContext('2d')
		if (!ctx) {
			cleanup()
			reject(new Error('failed to draw frame'))
			return
		}
		ctx.drawImage(video, 0, 0, canvas.width, canvas.height)
		const cover = canvas.toDataURL('image/jpeg', 0.92)
		const duration = video.duration
		cleanup()
		resolve({ duration, cover })
	}
})

const readFileAsDataUrl = (file: File) => new Promise<string>((resolve, reject) => {
	const reader = new FileReader()
	reader.onload = () => resolve(String(reader.result))
	reader.onerror = () => reject(new Error('read error'))
	reader.readAsDataURL(file)
})

const handleVideoUpload = async (options: UploadRequestOptions) => {
	const file = options.file as File
	uploadError.value = ''
	if (!file.type.startsWith('video')) {
		uploadError.value = '仅支持上传视频文件'
		options.onError?.(new Error('invalid file') as any)
		return
	}
	uploadingVideo.value = true
	videoUploadProgress.value = 0
	try {
		const { duration, cover } = await extractVideoDetails(file)
		const uploadResult = await uploadFileInChunksDirect(file, {
			chunkSize: 2 * 1024 * 1024,
			module: uploadModule,
			onProgress: pct => {
				videoUploadProgress.value = pct
			},
		})
		const apiResponse = uploadResult.response as ApiResponse<Record<string, any>>
		const mergedData = (apiResponse?.data ?? {}) as Record<string, any>
		videoDetails.file = file
		videoDetails.name = file.name
		videoDetails.size = file.size
		videoDetails.duration = duration
		videoDetails.resumeId = mergedData?.resumeId ? String(mergedData.resumeId) : ''
		videoDetails.filePath = mergedData?.filePath ?? ''
		videoDetails.fileName = mergedData?.originalFilename ?? mergedData?.fileName ?? file.name
		coverImage.value = cover
		uploadStep.value = 'details'
		ensureDefaultCourseSelection()
		options.onSuccess?.(null as any)
		ElMessage.success('视频上传成功')
	} catch (error) {
		uploadError.value = error instanceof Error ? error.message : '视频上传失败，请重试'
		options.onError?.(error as any)
		resetVideoMeta()
	} finally {
		uploadingVideo.value = false
	}
}

const handleCoverUpload = async (options: UploadRequestOptions) => {
	const file = options.file as File
	if (!file.type.startsWith('image')) {
		ElMessage.warning('请上传图片文件替换封面')
			options.onError?.(new Error('invalid image') as any)
		return
	}
	try {
		coverImage.value = await readFileAsDataUrl(file)
			options.onSuccess?.(null as any)
		ElMessage.success('封面已更新')
	} catch (error) {
			options.onError?.(error as any)
		ElMessage.error('封面上传失败，请重试')
	}
}

const ensureVideoReady = () => {
	if (!videoDetails.file || !videoDetails.resumeId) {
		ElMessage.warning('请先上传并完成视频处理')
		return false
	}
	return true
}

const handleSaveDraft = () => {
	if (!ensureVideoReady()) return
	if (!submissionForm.title.trim()) {
		ElMessage.warning('请填写视频标题后再保存草稿')
		return
	}
	ElMessage.success('草稿已保存，可在内容管理中继续编辑')
	submissionDrawerVisible.value = false
}

const handleSubmitSubmission = () => {
	if (!ensureVideoReady()) return
	submissionFormRef.value?.validate(valid => {
		if (!valid) return
		ElMessage.success('投稿已提交，待审核后会通知您')
		submissionDrawerVisible.value = false
	})
}

watch(() => submissionDrawerVisible.value, visible => {
	if (!visible) {
		resetSubmissionFlow()
	}
})

const resolveCategoryName = (value: string) => {
	const matched = categoryOptions.find(item => item.value === value)
	return matched ? matched.label : '未分类'
}

const countLessons = (course: CourseListItem) => course.chapters.reduce((sum, chapter) => sum + chapter.lessons.length, 0)

const courseEditorVisible = ref(false)
const editingCourseId = ref<string | null>(null)
const courseFormRef = ref<FormInstance>()

const courseForm = reactive({
	title: '',
	price: 0,
	category: '',
	status: 'REVIEWING' as CourseStatus,
	chapters: [] as CourseChapter[],
})

const courseFormRules: FormRules = {
	title: [
		{ required: true, message: '请输入课程标题', trigger: 'blur' },
		{ min: 4, message: '标题长度至少 4 个字符', trigger: 'blur' },
	],
	price: [
		{
			validator: (_rule, value, callback) => {
				if (value === null || value === undefined) {
					callback(new Error('请输入课程价格'))
				} else if (value < 0) {
					callback(new Error('价格不能为负数'))
				} else {
					callback()
				}
			},
			trigger: 'blur',
		},
	],
	category: [{ required: true, message: '请选择课程分类', trigger: 'change' }],
}

const resetCourseForm = () => {
	courseForm.title = ''
	courseForm.price = 0
	courseForm.category = ''
	courseForm.status = 'REVIEWING'
	courseForm.chapters.splice(0, courseForm.chapters.length)
	courseFormRef.value?.clearValidate()
}

const populateCourseForm = (course: CourseListItem) => {
	courseForm.title = course.title
	courseForm.price = course.price
	courseForm.category = course.category
	courseForm.status = course.status
	courseForm.chapters.splice(0, courseForm.chapters.length, ...JSON.parse(JSON.stringify(course.chapters)))
}

const handleAddCourse = () => {
	editingCourseId.value = null
	resetCourseForm()
	courseEditorVisible.value = true
}

const handleEditCourse = (course: CourseListItem) => {
	editingCourseId.value = course.id
	populateCourseForm(course)
	courseEditorVisible.value = true
}

const handleDeleteCourse = (courseId: string) => {
	ElMessageBox.confirm('课程删除后不可恢复，确认继续删除？', '删除课程', {
		type: 'warning',
		confirmButtonText: '删除',
		cancelButtonText: '取消',
	})
		.then(() => {
			const index = courses.findIndex(course => course.id === courseId)
			if (index !== -1) {
				courses.splice(index, 1)
				ElMessage.success('课程已删除')
			}
		})
		.catch(() => {})
}

const addChapter = () => {
	courseForm.chapters.push({ id: createId(), title: '', lessons: [] })
}

const removeChapter = (chapterIndex: number) => {
	courseForm.chapters.splice(chapterIndex, 1)
}

const addLesson = (chapterIndex: number) => {
	const chapter = courseForm.chapters[chapterIndex]
	if (chapter) {
		chapter.lessons.push({ id: createId(), title: '', duration: 0, assetId: '' })
	}
}

const removeLesson = (chapterIndex: number, lessonIndex: number) => {
	const chapter = courseForm.chapters[chapterIndex]
	if (chapter) {
		chapter.lessons.splice(lessonIndex, 1)
	}
}

const bindLessonWithAsset = (chapterIndex: number, lessonIndex: number, asset?: LessonAsset) => {
	if (!asset) return
	const chapter = courseForm.chapters[chapterIndex]
	if (!chapter) return
	const lesson = chapter.lessons[lessonIndex]
	if (!lesson) return
	lesson.assetId = asset.id
	lesson.duration = asset.duration
	if (!lesson.title.trim()) {
		lesson.title = asset.title
	}
}

const handleLessonAssetChange = (chapterIndex: number, lessonIndex: number) => {
	const chapter = courseForm.chapters[chapterIndex]
	if (!chapter) return
	const lesson = chapter.lessons[lessonIndex]
	if (!lesson) return
	const asset = findLessonAsset(lesson.assetId)
	if (!asset) {
		lesson.duration = 0
		return
	}
	bindLessonWithAsset(chapterIndex, lessonIndex, asset)
}

const handleInlineLessonUpload = async (
	chapterIndex: number,
	lessonIndex: number,
	options: UploadRequestOptions,
) => {
	const file = options.file as File
	if (!file.type.startsWith('video')) {
		ElMessage.warning('仅支持上传视频文件')
		options.onError?.(new Error('invalid file') as any)
		return
	}
	const key = getLessonUploadKey(chapterIndex, lessonIndex)
	inlineUploadProgress[key] = 0
	try {
		const { duration } = await extractVideoDetails(file)
		const uploadResult = await uploadFileInChunksDirect(file, {
			chunkSize: 2 * 1024 * 1024,
			module: uploadModule,
			onProgress: pct => {
				inlineUploadProgress[key] = pct
			},
		})
		const apiResponse = uploadResult.response as ApiResponse<Record<string, any>>
		const mergedData = (apiResponse?.data ?? {}) as Record<string, any>
		const asset: LessonAsset = {
			id: createId(),
			title: file.name.replace(/\.[^/.]+$/, ''),
			duration,
			uploadedAt: new Date().toISOString(),
			resumeId: mergedData?.resumeId ? String(mergedData.resumeId) : undefined,
			filePath: mergedData?.filePath,
			fileName: mergedData?.originalFilename ?? mergedData?.fileName ?? file.name,
		}
		lessonLibrary.unshift(asset)
		bindLessonWithAsset(chapterIndex, lessonIndex, asset)
		options.onSuccess?.(null as any)
		ElMessage.success('视频上传成功并已绑定到课时')
	} catch (error) {
		options.onError?.(error as any)
		ElMessage.error(error instanceof Error ? error.message : '视频上传失败，请重试')
	} finally {
		delete inlineUploadProgress[key]
	}
}

const getInlineUploadHandler = (chapterIndex: number, lessonIndex: number) =>
	(options: UploadRequestOptions) =>
		handleInlineLessonUpload(chapterIndex, lessonIndex, options)

const handleCourseSubmit = () => {
	courseFormRef.value?.validate(valid => {
		if (!valid) return
		if (!courseForm.chapters.length) {
			ElMessage.warning('请至少添加一个章节')
			return
		}
		const hasUnboundLesson = courseForm.chapters.some(
			chapter => !chapter.lessons.length || chapter.lessons.some(lesson => !lesson.assetId),
		)
		if (hasUnboundLesson) {
			ElMessage.warning('请为每个课时选择或上传视频')
			return
		}
		const payload: CourseListItem = {
			id: editingCourseId.value ?? createId(),
			title: courseForm.title.trim(),
			price: Number(courseForm.price),
			category: courseForm.category,
			status: courseForm.status,
			createdAt: editingCourseId.value
				? courses.find(course => course.id === editingCourseId.value)?.createdAt ?? new Date().toISOString().slice(0, 10)
				: new Date().toISOString().slice(0, 10),
			chapters: JSON.parse(JSON.stringify(courseForm.chapters)),
			enrollments: editingCourseId.value
				? courses.find(course => course.id === editingCourseId.value)?.enrollments ?? 0
				: 0,
			rating: editingCourseId.value
				? courses.find(course => course.id === editingCourseId.value)?.rating ?? 0
				: 0,
			comments: editingCourseId.value
				? courses.find(course => course.id === editingCourseId.value)?.comments ?? 0
				: 0,
			completion: editingCourseId.value
				? courses.find(course => course.id === editingCourseId.value)?.completion ?? 0
				: 0,
		}

		if (editingCourseId.value) {
			const index = courses.findIndex(course => course.id === editingCourseId.value)
			if (index !== -1) {
				courses.splice(index, 1, payload)
			}
			ElMessage.success('课程信息已更新')
		} else {
			courses.unshift(payload)
			ElMessage.success('课程已创建，请继续完善内容')
		}

		courseEditorVisible.value = false
	})
}

const totalCourses = computed(() => courses.length)
const publishedCount = computed(() => courses.filter(course => course.status === 'PUBLISHED').length)
const reviewCount = computed(() => courses.filter(course => course.status === 'REVIEWING').length)
const publishRate = computed(() => (totalCourses.value ? Math.round((publishedCount.value / totalCourses.value) * 100) : 0))
const reviewRate = computed(() => (totalCourses.value ? Math.round((reviewCount.value / totalCourses.value) * 100) : 0))

const totalEnrollments = computed(() => courses.reduce((sum, course) => sum + course.enrollments, 0))
const totalRevenue = computed(() => courses.reduce((sum, course) => sum + course.enrollments * course.price, 0))
const averageRating = computed(() => {
	const rated = courses.filter(course => course.rating > 0)
	if (!rated.length) return 0
	return rated.reduce((sum, course) => sum + course.rating, 0) / rated.length
})
const averageCompletionRate = computed(() => {
	const recorded = courses.filter(course => course.completion > 0)
	if (!recorded.length) return 0
	const value = recorded.reduce((sum, course) => sum + course.completion, 0) / recorded.length
	return Math.round(value)
})

const highEngagementCourse = computed(() => {
	if (!courses.length) return '暂无课程'
	return [...courses].sort((a, b) => b.comments - a.comments)[0]?.title ?? '暂无课程'
})

const weeklyComments = computed(() => comments.length * 3)

const metricCards = computed(() => [
	{ title: '课程总数', value: totalCourses.value, note: '包含全部课程记录' },
	{ title: '已发布课程', value: publishedCount.value, note: `发布率 ${publishRate.value}%` },
	{ title: '累计学员', value: totalEnrollments.value.toLocaleString(), note: '统计报名总人次' },
	{ title: '预计收益', value: `¥${totalRevenue.value.toLocaleString()}`, note: '按课程定价与报名人数估算' },
	{ title: '平均评分', value: averageRating.value ? averageRating.value.toFixed(1) : '—', note: '来源课程评价与互动' },
])

const topCourses = computed(() => [...courses].sort((a, b) => b.enrollments - a.enrollments).slice(0, 5))

const replyDialogVisible = ref(false)
const replyForm = reactive({ content: '' })
const replyingCommentId = ref<string | null>(null)

const openReplyDialog = (comment: CommentItem) => {
	replyingCommentId.value = comment.id
	replyForm.content = ''
	replyDialogVisible.value = true
}

const resetReplyForm = () => {
	replyingCommentId.value = null
	replyForm.content = ''
}

const handleSubmitReply = () => {
	if (!replyForm.content.trim()) {
		ElMessage.warning('请输入回复内容')
		return
	}
	const comment = comments.find(item => item.id === replyingCommentId.value)
	if (!comment) return
	comment.replies.push({
		id: createId(),
		author: '讲师团队',
		content: replyForm.content.trim(),
		createdAt: new Date().toISOString(),
	})
	ElMessage.success('回复已发送')
	replyDialogVisible.value = false
}

const handleDeleteComment = (commentId: string) => {
	ElMessageBox.confirm('删除后学员评论将不可恢复，确认删除？', '删除评论', {
		type: 'warning',
		confirmButtonText: '删除',
		cancelButtonText: '取消',
	})
		.then(() => {
			const index = comments.findIndex(comment => comment.id === commentId)
			if (index !== -1) {
				comments.splice(index, 1)
				ElMessage.success('评论已删除')
			}
		})
		.catch(() => {})
}

const replyDialogTitle = computed(() => {
	const comment = comments.find(item => item.id === replyingCommentId.value)
	if (!comment) return '学员互动'
	return `${comment.userName} · ${comment.courseTitle}`
})

watch(
	() => courses.map(course => ({ id: course.id, title: course.title })),
	mapped => {
		const titleMap = new Map(mapped.map(item => [item.id, item.title]))
		comments.forEach(comment => {
			comment.courseTitle = titleMap.get(comment.courseId) ?? comment.courseTitle
		})
	},
	{ deep: true },
)

const formatDuration = (seconds: number) => {
	const total = Math.round(seconds)
	const h = Math.floor(total / 3600)
	const m = Math.floor((total % 3600) / 60)
	const s = total % 60
	const mm = m.toString().padStart(2, '0')
	const ss = s.toString().padStart(2, '0')
	if (h > 0) {
		return `${h}:${mm}:${ss}`
	}
	return `${mm}:${ss}`
}

const formatFileSize = (size: number) => {
	if (!size) return '0 B'
	const units = ['B', 'KB', 'MB', 'GB']
	let index = 0
	let value = size
	while (value >= 1024 && index < units.length - 1) {
		value /= 1024
		index += 1
	}
	return `${value.toFixed(value >= 100 ? 0 : 1)} ${units[index]}`
}

const formatDate = (input: string) => {
	const date = new Date(input)
	if (Number.isNaN(date.getTime())) return input
	return `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date
		.getDate()
		.toString()
		.padStart(2, '0')} ${date.getHours().toString().padStart(2, '0')}:${date
		.getMinutes()
		.toString()
		.padStart(2, '0')}`
}
</script>

<style scoped>
.course-manager {
	min-height: 100vh;
	background-color: #f6f7fb;
	display: flex;
	flex-direction: column;
}

.course-manager__body {
	flex: 1;
	display: flex;
	align-items: stretch;
	gap: 0;
}

.course-manager__sidebar {
	width: 240px;
	background-color: #ffffff;
	border-right: 1px solid #e5e7eb;
	padding: 24px 16px;
	display: flex;
	flex-direction: column;
	gap: 24px;
}

.sidebar__cta {
	display: flex;
	flex-direction: column;
	gap: 12px;
}

.sidebar__post-btn {
	width: 100%;
}

.sidebar__menu {
	border-right: none;
}

.course-manager__main {
	flex: 1;
	padding: 32px 40px 64px;
	display: flex;
	flex-direction: column;
	gap: 32px;
}

.section {
	display: flex;
	flex-direction: column;
	gap: 24px;
}

.section__header {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 24px;
}

.section__header h1 {
	margin: 0;
	font-size: 28px;
	font-weight: 600;
	color: #1f2d3d;
}

.section__header p {
	margin: 6px 0 0;
	color: #5c6b7a;
}

.section__card {
	background-color: #ffffff;
}

.card-header {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	font-weight: 600;
	color: #1f2d3d;
}

.metrics-grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
	gap: 16px;
}

.metric-card {
	display: flex;
	flex-direction: column;
	gap: 4px;
	border-radius: 12px;
	background: #ffffff;
}

.metric-card__title {
	font-size: 14px;
	color: #5c6b7a;
}

.metric-card__value {
	font-size: 28px;
	font-weight: 600;
	color: #1f2d3d;
}

.metric-card__note {
	font-size: 13px;
	color: #8591a2;
}

.data-layout {
	display: grid;
	grid-template-columns: 1.4fr 1fr;
	gap: 24px;
}

.data-card {
	background-color: #ffffff;
}

.progress-list {
	display: flex;
	flex-direction: column;
	gap: 16px;
	margin-bottom: 24px;
}

.progress-item {
	display: flex;
	flex-direction: column;
	gap: 8px;
}

.progress-item__label {
	font-weight: 500;
	color: #1f2d3d;
}

.data-summary {
	border-radius: 8px;
}

.reply-list {
	display: flex;
	flex-direction: column;
	gap: 16px;
	padding: 8px 0;
}

.reply-list__empty {
	color: #8591a2;
}

.reply-item {
	background-color: #f6f8fb;
	padding: 12px 16px;
	border-radius: 8px;
}

.reply-item__meta {
	display: flex;
	justify-content: space-between;
	align-items: center;
	margin-bottom: 6px;
	color: #5c6b7a;
}

.submission-drawer {
	height: 100%;
	display: flex;
	flex-direction: column;
	gap: 24px;
	padding: 24px 8px 48px 24px;
}

.submission-drawer__header h2 {
	margin: 0;
	font-size: 24px;
	font-weight: 600;
	color: #1f2d3d;
}

.submission-drawer__header p {
	margin: 8px 0 0;
	color: #5c6b7a;
}

.submission-upload {
	flex: 1;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 12px;
	background: #f6f8fb;
	border-radius: 12px;
	padding: 48px;
	color: #5c6b7a;
}

.submission-upload__icon {
	font-size: 40px;
	color: #409eff;
}

.submission-upload__title {
	font-size: 18px;
	color: #1f2d3d;
	margin: 0;
}

.submission-upload__tips {
	margin: 0;
}

.submission-upload__progress {
	width: 100%;
	max-width: 420px;
	margin-top: 16px;
}

.submission-upload__error {
	color: #ff4d4f;
	margin-top: 12px;
}

.submission-form {
	display: flex;
	flex-direction: column;
	gap: 24px;
}

.submission-form__info {
	background: #ffffff;
}

.submission-form__fields {
	background: #ffffff;
	padding: 24px;
	border-radius: 12px;
}

.cover-field {
	display: flex;
	align-items: center;
	gap: 16px;
}

.cover-preview {
	width: 160px;
	height: 90px;
	border-radius: 8px;
	overflow: hidden;
	background: #1f2d3d;
}

.cover-preview img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.cover-preview--placeholder {
	display: flex;
	align-items: center;
	justify-content: center;
	background: #f0f2f5;
	color: #8591a2;
}

.submission-form__actions {
	display: flex;
	justify-content: flex-end;
	gap: 16px;
}

.dialog-header h3 {
	margin: 0;
	font-size: 22px;
	font-weight: 600;
	color: #1f2d3d;
}

.dialog-header p {
	margin: 6px 0 0;
	color: #5c6b7a;
}

.course-form {
	display: flex;
	flex-direction: column;
	gap: 12px;
}

.course-form__tip {
	margin-left: 12px;
	color: #8591a2;
}

.course-form__tip--inline {
	margin-left: 16px;
}

.chapters-editor {
	display: flex;
	flex-direction: column;
	gap: 16px;
	width: 100%;
}

.chapter-card {
	border: 1px solid #e5e7eb;
	border-radius: 12px;
	padding: 16px;
	display: flex;
	flex-direction: column;
	gap: 12px;
	background: #fefefe;
}

.chapter-card__header {
	display: flex;
	align-items: center;
	gap: 12px;
}

.chapter-card__lessons {
	display: flex;
	flex-direction: column;
	gap: 12px;
}

.lesson-item {
	display: grid;
	grid-template-columns: minmax(200px, 1.2fr) minmax(260px, 1.6fr) minmax(160px, 0.9fr) auto;
	gap: 12px;
	align-items: center;
}

.lesson-item__title,
.lesson-item__source,
.lesson-item__duration-display {
	width: 100%;
}

.lesson-item__source {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	align-items: center;
}

.lesson-item__upload :deep(.el-upload) {
	display: inline-flex;
}

.lesson-item__duration-display {
	color: #1f2d3d;
}

.lesson-item__duration-placeholder {
	color: #b4bfd0;
}

.lesson-item__actions {
	display: flex;
	justify-content: flex-end;
	align-items: center;
	gap: 12px;
	flex-wrap: wrap;
	width: auto;
}

.lesson-item__progress {
	display: flex;
	align-items: center;
	min-height: 42px;
	margin-left: 4px;
}

.dialog-footer {
	display: flex;
	justify-content: flex-end;
	gap: 12px;
}

@media (max-width: 1200px) {
	.course-manager__main {
		padding: 28px 24px 56px;
	}

	.data-layout {
		grid-template-columns: 1fr;
	}
}

@media (max-width: 960px) {
	.course-manager__body {
		flex-direction: column;
	}

	.course-manager__sidebar {
		width: 100%;
		flex-direction: row;
		align-items: center;
		justify-content: space-between;
		gap: 16px;
	}

	.sidebar__menu {
		flex: 1;
		display: flex;
	}

	:deep(.sidebar__menu .el-menu-item) {
		flex: 1;
	}

	.lesson-item {
		grid-template-columns: repeat(2, minmax(200px, 1fr));
		grid-auto-rows: auto;
		align-items: flex-start;
	}

	.lesson-item__duration-display,
	.lesson-item__actions,
	.lesson-item__progress {
		grid-column: 1 / -1;
	}
}

@media (max-width: 640px) {
	.course-manager__main {
		padding: 24px 16px 48px;
	}

	.section__header {
		flex-direction: column;
		align-items: flex-start;
	}

	.lesson-item {
		grid-template-columns: 1fr;
		gap: 10px;
		align-items: flex-start;
	}

	.lesson-item__source {
		flex-direction: column;
		align-items: stretch;
	}

	.lesson-item__actions {
		justify-content: flex-start;
	}

	.lesson-item__progress {
		justify-content: flex-start;
	}

	.cover-field {
		flex-direction: column;
		align-items: flex-start;
	}
}
</style>
